<template>
  <MenuPage
    :data="vulnerabilityList"
    :columns="vulnerabilityCol"
    :page.sync="queryParams.pageIndex"
    :size.sync="queryParams.pageSize"
    :total="vulnerabilityTotal"
    :loading="vulnerabilityLoading"
    @queryFun="getVulnerabilityList">
    <template slot="search">
      <Select filterable clearable v-model="queryParams.level" @on-change="changePage(1)" placeholder="漏洞评级" style="margin-left: 15px;width: 150px">
        <Option v-for="level in levelList" :key="level.value" :value="level.value">{{level.label}}</Option>
      </Select>
      <Select filterable clearable v-model="queryParams.vulnerabilityType" @on-change="changePage(1)" placeholder="漏洞类型" style="margin-left: 15px;width: 150px">
        <Option v-for="(item, key) in assetVulnerabilityTypeOptions" :key="key" :value="key">{{item}}</Option>
      </Select>
      <Input v-model.trim="queryParams.name"  clearable placeholder="漏洞名称" @on-change="changePage(1)" style="width: 180px;margin-left: 15px" />
      <Input v-model.trim="queryParams.productName"  clearable placeholder="关联产品" @on-change="changePage(1)" style="width: 180px;margin-left: 15px" />
      <Input v-model.trim="queryParams.ip"  clearable placeholder="IP" @on-change="changePage(1)" style="width: 180px;margin-left: 15px" />
      <Input v-model.trim="queryParams.port"  clearable placeholder="端口" @on-change="changePage(1)" style="width: 180px;margin-left: 15px" />
      <Input v-model.trim="queryParams.url"  clearable placeholder="地址" @on-change="changePage(1)" style="width: 180px;margin-left: 15px" />
      <DatePicker
          :editable="false"
          type="datetimerange"
          :value="times"
          format="yyyy-MM-dd HH:mm:ss"
          placement="bottom-start"
          confirm
          ref="datePicker"
          placeholder="起止时间"
          transfer
          @on-change="changeDates"
          style="width: 320px"
      ></DatePicker>
      <Button class="header-btn" type="primary" ghost style="height: 32px;margin-left: 5px;" @click="refreshVulnerability()">
        <i class="el-icon-refresh-right" />
      </Button>
    </template>
    <Modal
      v-model="detailModalData.showPart"
      title="部件详情"
      footer-hide
      class="my-modal">
      <div class="item-table">
        <p>
          <span class='label'>部件名称</span>
          <span>{{detailInfo.name}}</span>
        </p>
        <p>
          <span class='label'>软硬件</span>
          <span>{{['软件', '硬件'][detailInfo.type]}}</span>
        </p>
        <p>
          <span class='label'>供应商</span>
          <span>{{detailInfo.supplier}}</span>
        </p>
        <p>
          <span class='label'>部件类型</span>
          <span>{{partTypeOptions[detailInfo.partType]}}</span>
        </p>
        <p>
          <span class='label'>型号</span>
          <span>{{detailInfo.model}}</span>
        </p>
        <p>
          <span class='label'>版本</span>
          <span>{{detailInfo.version}}</span>
        </p>
        <p>
          <span class='label'>包URL</span>
          <span>{{detailInfo.groupAddress}}</span>
        </p>
        <p>
          <span class='label'>CPE名称</span>
          <span>{{detailInfo.enumItem}}</span>
        </p>
        <p>
          <span class='label'>软件标识标签</span>
          <span>{{detailInfo.swid}}</span>
        </p>
        <p>
          <span class='label'>对象标识</span>
          <span>{{detailInfo.objectId}}</span>
        </p>
        <p>
          <span class='label'>文件名称</span>
          <span>{{detailInfo.fileName}}</span>
        </p>
        <p>
          <span class='label'>描述</span>
          <span>{{detailInfo.description}}</span>
        </p>
        <p>
          <span class='label'>MD5</span>
          <span>{{detailInfo.md5}}</span>
        </p>
        <p>
          <span class='label'>SHA1</span>
          <span>{{detailInfo.sha1}}</span>
        </p>
        <p>
          <span class='label'>SHA256</span>
          <span>{{detailInfo.sha256}}</span>
        </p>
        <p>
          <span class='label'>SHA384</span>
          <span>{{detailInfo.sha384}}</span>
        </p>
        <p>
          <span class='label'>SHA512</span>
          <span>{{detailInfo.sha512}}</span>
        </p>
        <p>
          <span class='label'>SHA3 256</span>
          <span>{{detailInfo.sha3256}}</span>
        </p>
        <p>
          <span class='label'>SHA3 512</span>
          <span>{{detailInfo.sha3512}}</span>
        </p>
        <p>
          <span class='label'>注意事项</span>
          <span>{{detailInfo.announcements}}</span>
        </p>
      </div>
    </Modal>
    <Modal
      v-model="detailModalData.showModule"
      title="组件详情"
      footer-hide
      class="my-modal">
      <div class="item-table">
        <p>
          <span class='label'>组件名称</span>
          <span>{{ detailInfo.name }}</span>
        </p>
        <p>
          <span class='label'>组件类型</span>
          <span>{{ typeOptions[detailInfo.type] && typeOptions[detailInfo.type].label }}</span>
        </p>
        <p>
          <span class='label'>物料清单引用标识</span>
          <span>{{ detailInfo.bomId }}</span>
        </p>
        <p>
          <span class='label'>版本号</span>
          <span>{{ detailInfo.version }}</span>
        </p>
        <p>
          <span class='label'>分组</span>
          <span>{{ detailInfo.groupId }}</span>
        </p>
        <p>
          <span class='label'>最新版本</span>
          <span>{{ detailInfo.latestVersion }}</span>
        </p>
        <p>
          <span class='label'>作者</span>
          <span>{{ detailInfo.author }}</span>
        </p>
        <p>
          <span class='label'>供应商</span>
          <span>{{ detailInfo.publisher }}</span>
        </p>
        <p>
          <span class='label'>包URL</span>
          <span>{{ detailInfo.groupAddress }}</span>
        </p>
        <p>
          <span class='label'>CPE名称</span>
          <span>{{ detailInfo.enumItem }}</span>
        </p>
        <p>
          <span class='label'>软件标识标签</span>
          <span>{{ detailInfo.swid }}</span>
        </p>
        <p>
          <span class='label'>对象标识</span>
          <span>{{ detailInfo.objectId }}</span>
        </p>
        <p>
          <span class='label'>文件名称</span>
          <span>{{ detailInfo.fileName }}</span>
        </p>
        <p>
          <span class='label'>描述</span>
          <span>{{ detailInfo.description }}</span>
        </p>
        <p>
          <span class='label'>许可类型</span>
          <span>{{ detailInfo.licenseType }}</span>
        </p>
        <p>
          <span class='label'>许可文件链接</span>
          <span>{{ detailInfo.licenseFileLink }}</span>
        </p>
        <p>
          <span class='label'>版权说明</span>
          <span>{{ detailInfo.licenseDescription }}</span>
        </p>
        <p>
          <span class='label'>MD5</span>
          <span>{{ detailInfo.md5 }}</span>
        </p>
        <p>
          <span class='label'>SHA1</span>
          <span>{{ detailInfo.sha1 }}</span>
        </p>
        <p>
          <span class='label'>SHA256</span>
          <span>{{ detailInfo.sha256 }}</span>
        </p>
        <p>
          <span class='label'>SHA512</span>
          <span>{{ detailInfo.sha512 }}</span>
        </p>
        <p>
          <span class='label'>SHA3 256</span>
          <span>{{ detailInfo.sha3256 }}</span>
        </p>
        <p>
          <span class='label'>SHA3 512</span>
          <span>{{ detailInfo.sha3512 }}</span>
        </p>
        <p>
          <span class='label'>注意事项</span>
          <span>{{ detailInfo.announcements }}</span>
        </p>
      </div>
    </Modal>
    <VulnerabilityDetail
      ref="VulnerabilityDetail"></VulnerabilityDetail>
    <Modal
      v-model="showHistoryModal"
      title="漏洞日志"
      footer-hide
      class="my-modal"
    >
      <HistoryPage
                   :isBug="false"
                   ref="historyPage"
      >
      </HistoryPage>
    </Modal>
    <Modal
      v-model="modalData.show"
      title="漏洞评估"
      class="my-modal"
      @on-visible-change="changeVisible">
      <Form
        ref="formInline"
        :label-width="90"
        :model="formData"
        :rules="customRules">
        <FormItem prop="attackPath" label="攻击路径">
          <Select filterable transfer filterable clearable v-model="formData.attackPath" placeholder="">
            <Option value="远程攻击">远程攻击</Option>
            <Option value="本地攻击">本地攻击</Option>
            <Option value="社会工程学攻击">社会工程学攻击</Option>
            <Option value="供应链攻击">供应链攻击</Option>
            <Option value="内部攻击">内部攻击</Option>
          </Select>
        </FormItem>
        <FormItem prop="attackLevel" label="攻击难度">
          <Select filterable transfer filterable clearable v-model="formData.attackLevel" placeholder="">
            <Option value="低难度">低难度</Option>
            <Option value="中等难度">中等难度</Option>
            <Option value="高难度">高难度</Option>
          </Select>
        </FormItem>
        <FormItem prop="powerRequest" label="权限要求">
          <Select filterable transfer filterable clearable v-model="formData.powerRequest" placeholder="" :disabled="!isWeakPassword">
            <Option value="无权限要求">无权限要求</Option>
            <Option value="低权限要求">低权限要求</Option>
            <Option value="中等权限要求">中等权限要求</Option>
            <Option value="高权限要求">高权限要求</Option>
          </Select>
        </FormItem>
        <FormItem prop="impactRange" label="影响范围">
          <Select filterable transfer filterable clearable v-model="formData.impactRange" placeholder="">
            <Option value="跨系统影响">跨系统影响</Option>
            <Option value="全面影响">全面影响</Option>
            <Option value="部分影响">部分影响</Option>
            <Option value="局部影响">局部影响</Option>
          </Select>
        </FormItem>
        <FormItem prop="serverDamage" label="服务器危害">
          <Select filterable transfer filterable clearable v-model="formData.serverDamage" placeholder="">
            <Option value="数据泄露">数据泄露</Option>
            <Option value="服务中断">服务中断</Option>
            <Option value="恶意操作">恶意操作</Option>
          </Select>
        </FormItem>
        <FormItem prop="publicPocOrExp" label="是否有公开POC或EXP">
          <Select filterable transfer filterable clearable v-model="formData.publicPocOrExp" placeholder="">
            <Option value="是">是</Option>
            <Option value="否">否</Option>
          </Select>
        </FormItem>
      </Form>
      <div slot="footer" class="footer">
        <Button @click="modalData.show = false">取消</Button>
        <Button @click="save" :loading="modalData.loading" type="primary">确定</Button>
      </div>
    </Modal>
  </MenuPage>
</template>
<script>
import encryption from '@/libs/encryption.js'
import VulnerabilityDetail from './detail/vulnerability-detail.vue'
import HistoryPage from './detail/history-page.vue'
import {vulnerabilityLevelEscape} from './logic/vulnerabilityLogic'
import { estimateVulnerability } from '@/view/testPlatform/vulnerability/api/vulnerability.js'
import * as paramsConfig from '../paramsConfig'
import {
  queryVulnerabilityListNew,getModuleDetail
} from './api/vulnerability'
export default {
  components: {VulnerabilityDetail,HistoryPage},
  data () {
    return {
      assetVulnerabilityTypeOptions: {
          backdoor: '后门',
          'bak-file-found': '发现备份文件',
          'buffer-overflow': '缓冲区溢出',
          'cmd-exec': '命令执行',
          'code-exec': '代码执行',
          'dir-listing': '目录遍历',
          'dir-traversal': '目录穿越',
          dos: '拒绝服务攻击',
          'file-creation': '文件创建',
          'file-deletion': '文件删除',
          'file-download': '文件下载',
          'file-read': '文件读取',
          'file-upload': '文件上传',
          finger: '信息搜集',
          'improper-input-validation': '不当的输入验证',
          'info-disclosure': '信息泄露',
          'ldap-inj': 'LDAP注入',
          lfi: '本地文件包含',
          'login-bypass': '登录绕过',
          'path-disclosure': '路径泄露',
          'privilege-escalation': '提权攻击',
          redirect: '重定向',
          'remote-pass-change': '远程密码修改',
          'resolve-error': '解析错误',
          rfi: '远程文件包含',
          'sec-bypass': '安全绕过',
          'sql-inj': 'SQL注入',
          'ssi-inj': '服务器端包含注入',
          ssrf: '服务器端请求伪造',
          'unauth-access': '未授权访问',
          'xml-inj': 'XML注入',
          'xpath-inj': 'XPath注入',
          xss: '跨站脚本攻击',
          injection: '注入攻击',
          xxe: 'XML外部实体注入',
          'file_upload': '文件上传攻击',
          'file_operation': '文件操作攻击',
          'file_traversal': '文件遍历攻击',
          'file_download': '文件下载攻击',
          rce: '远程代码执行',
          'info_leak': '信息泄露攻击',
          misconfiguration: '配置错误',
          weakpass: '弱口令攻击',
          other: '其它攻击',
      },
      queryParams:{
        pageIndex:1,
        pageSize:10
      },
      times: [],
      // 用户信息
      USER_ID: '',
      isRootDesinger: '',

      histroryList:[],
      showHistoryModal:false,
      modalData: {
        show: false,
        loading: false
      },
      vulnerabilityLoading: false,
      levelList:[
        {value:0,label:'超危'},
        {value:1,label:'高危'},
        {value:2,label:'中危'},
        {value:3,label:'低危'},
      ],
      vulnerabilityTotal: 0,
      vulnerabilityList: [],
      vulnerabilityCol: [
        {
          title: '漏洞名称',
          key: 'name',
          tooltip: true,
        },
        {
          title: '漏洞评级',
          key: 'level',
          render: (h, params) => {
            let ret = vulnerabilityLevelEscape(params.row.level)
            return h('Tag', {
              props: {
                color: ret.color
              },
              style: {
                width: '70px',
                'text-align': 'center'
              }
            }, ret.text)
          }
        },
        {
          title: '漏洞评分',
          key: 'value',
          tooltip: true,
        },
        {
          title: '漏洞类型',
          key: 'vulnerabilityType',
          tooltip: true,
          render: (h, params) => {
            if (params.row.vulnerabilityType) {
              let content = this.assetVulnerabilityTypeOptions[params.row.vulnerabilityType]
              return h('Tooltip', {
                  props: {
                      'max-width': '300',
                      transfer: true,
                      content
                  },
                  style: {
                      width: '100%',
                  }
              }, [
                  h('p', {
                      style: {
                          overflow: 'hidden',
                          'text-overflow': 'ellipsis'
                      }
                  }, content)
              ])
            } else {
              return h('span', '-')
            }
          }
        },
        {
          title: '关联产品',
          key: 'productName',
          tooltip: true,
        },
        {
          title: 'IP',
          key: 'ip',
          tooltip: true,
        },
        {
          title: '端口',
          key: 'port',
          tooltip: true,
        },
        {
          title: '地址',
          key: 'url',
          tooltip: true,
        },
        {
          title: '是否评估',
          key: 'isAssess',
          render: (h, params) => {
            let { attackLevel, attackPath, impactRange, powerRequest, serverDamage, publicPocOrExp } = params.row
            // 任何一个参数有值，表示已评估
            let isAssess = attackLevel || attackPath || impactRange || powerRequest || serverDamage || publicPocOrExp
            return h('Tag', {
              props: {
                color: isAssess ? 'green' : 'orange'
              },
              style: {
                width: '70px',
                'text-align': 'center'
              }
            }, isAssess ? '是' : '否')
          }
        },
        {
          title: '操作',
          width: 240,
          slot: 'action',
          opList: [
            {

              txt: '详情',
              on:{
                click:(data,e) => {
                  this.showDetail(data)

                }
              },
            },
            {
              txt: '日志',
              on:{
                click:(data,e) => {
                  this.showHistory(data)
                }
              },
            },
            {
              txt: '评估',
              on:{
                click:(data,e) => {
                  this.showAssess(data)
                }
              },
            }
          ]
        }
      ],
      typeOptions:paramsConfig.typeOptions.map((item, index) => {
        return {
          value: index,
          label: item
        }
      }).filter(item => [1, 2, 3, 4, 5].includes(item.value)),
      partTypeOptions:paramsConfig.typeOptions,
      detailModalData: {
        showPart: false,
        showModule: false
      },
      detailInfo:{},
      formData: {
        id: '',
        name: '',
        attackPath: '',
        attackLevel: '',
        powerRequest: '',
        impactRange: '',
        serverDamage: '',
        publicPocOrExp: ''
      },
      isWeakPassword: false,
      customRules: {
        // attackPath: [
        //   { required: true, type: 'number', message: '攻击路径不能为空', trigger: 'change' },
        // ],
        // attackLevel: [
        //   { required: true, type: 'number', message: '攻击难度不能为空', trigger: 'change' },
        // ],
        // powerRequest: [
        //   { required: true, type: 'number', message: '权限要求不能为空', trigger: 'change' },
        // ],
        // impactRange: [
        //   { required: true, type: 'number', message: '影响范围不能为空', trigger: 'change' },
        // ],
        // serverDamage: [
        //   { required: true, type: 'number', message: '服务器危害不能为空', trigger: 'change' },
        // ],
        // publicPocOrExp: [
        //   { required: true, type: 'number', message: '是否有公开POC或EXP不能为空', trigger: 'change' },
        // ],
      }
    }
  },

  created () {
    // 获取用户id
    let November = sessionStorage.getItem('November')
    November = JSON.parse(encryption.SelfUseDecrypt(November))
    this.USER_ID = November.userId
    this.isRootDesinger = November.isRootDesinger
    this.distributed = November.distributed
    // this.distributedRange = this.$store.state.user.distributedRange
  },
  mounted () {
    let getPage = this.$route.query.page ? parseInt(this.$route.query.page) : 1
    this.queryParams.pageIndex = getPage
    this.getVulnerabilityList()
  },
  methods: {
    // 隐藏模态框时，重置表单数据
    changeVisible(type) {
        if (!type) {
            this.$refs.formInline.resetFields()
            this.modalData.loading = false
        }
    },
    save() {
      this.$refs.formInline.validate(valid => {
          if (valid) {
              this.modalData.loading = true
              let data = Object.assign({}, this.formData)
              data.attackPath = data.attackPath ? data.attackPath : '-'
              data.attackLevel = data.attackLevel ? data.attackLevel : '-'
              data.powerRequest = data.powerRequest ? data.powerRequest : '-'
              data.impactRange = data.impactRange ? data.impactRange : '-'
              data.serverDamage = data.serverDamage ? data.serverDamage : '-'
              data.publicPocOrExp = data.publicPocOrExp ? data.publicPocOrExp : '-'
              estimateVulnerability(data).then(({ code, message }) => {
                  if (code !== 1) {
                      this.$Message.warning(message)
                      return
                  }
                  // 创建成功
                  this.$Message.success(`评估漏洞成功`)
                  this.getVulnerabilityList()
                  this.modalData.show = false
              }).catch(() => {
                  this.$Message.error(`评估漏洞异常`)
              }).finally(() => {
                  this.modalData.loading = false
              })
          }
      })
    },
    changeDates(timeList) {
        if (timeList && timeList[0]) {
            this.queryParams.createdStart = timeList[0];
            this.queryParams.createdEnd = timeList[1];
        } else {
            this.queryParams.createdStart = '';
            this.queryParams.createdEnd = '';
        }
        this.changePage(1)
    },
    getVulnerabilityList (isRefresh) {
      if (!isRefresh) { // 非刷新操作才需要展示等待中的画面
        this.vulnerabilityLoading = true
      }
      queryVulnerabilityListNew(this.queryParams)
        .then(res => {
          if (res.code == 1) {
            this.vulnerabilityTotal =res.data.total;
            this.vulnerabilityList = res.data.items
          }
          this.vulnerabilityLoading = false
        })
        .catch(err => {
          this.vulnerabilityLoading = false
        })
    },
    changePage(val) {
      this.queryParams.pageIndex = val
      this.getVulnerabilityList()
    },
    // 刷新镜像
    refreshVulnerability() {
      this.queryParams = {
        pageIndex:1,
        pageSize:10
      }
      this.getVulnerabilityList()
    },
    showDetail(data){
      this.$refs.VulnerabilityDetail.getVulnerabilityDetail(data.id)
    },
    showHistory(data){
      this.showHistoryModal = true;
      this.$refs.historyPage.getBugLogOrVulnerabilityLogList(data);
    },
    showAssess(obj) {
      this.modalData.show = true
      this.formData.id = obj.id
      this.formData.name = obj.name
      this.formData.attackPath = obj.attackPathStr || ''
      this.formData.attackLevel = obj.attackLevelStr || ''
      this.formData.powerRequest = obj.powerRequestStr || ''
      this.formData.impactRange = obj.impactRangeStr || ''
      this.formData.serverDamage = obj.serverDamageStr || ''
      this.formData.publicPocOrExp = obj.publicPocOrExpStr || ''
      this.isWeakPassword = obj.vulnerabilityType && obj.vulnerabilityType.toLowerCase() === 'weakpass'
    },
    showPartOrModuleDetail(moduleId) {
      getModuleDetail(moduleId).then(({ code, message, data = {} }) => {
        if (code !== 1) {
          this.$Message.warning(message)
          return
        }
        if (data.productComponent) { // 组件
          this.detailModalData.showModule = true
        } else { // 部件
          this.detailModalData.showPart = true
        }
        this.detailInfo = data.productComponent || data.productPart || {}
      })
    },
  },
  beforeDestroy () {

  }
}
</script>
<style scoped>
.item-table {
  display: table;
  width: 100%;
  border: 1px solid #eee;
  table-layout: fixed;
  word-break: break-all;
}
.item-table p {
  display: table-row;
  line-height: 36px;
  text-align: center;
}
.item-table p span {
  display: table-cell;
  border-bottom: 1px solid #eee;
}
.ios-alert {
  /* position: absolute;
        top: -44px;
        right: -404px; */
  color: orange;
  font-size: 16px;
  cursor: pointer;
}
.too {
  position: absolute;
  left: 113px;
  top: -1px;
}
</style>
